package com.booter.ws.tinyurl;

import java.util.HashMap;
import java.util.Map;

/**
 * @author xueqiu
 * @date 2023/11/17 10:32
 * <p>
 * 62进制转10进制，从右往左每个数*62的N次方，N从0开始。
 * 转62进制不断除以62取余数，然后倒序。
 * <p>
 */
public class Base62 {

    public static final String BASE_62_CHAR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    public static final int BASE = BASE_62_CHAR.length();

    public static long toBase10(String str) {
        //从右边开始
        return toBase10(new StringBuilder(str).reverse().toString().toCharArray());
    }

    private static long toBase10(char[] chars) {
        long n = 0;
        int pow = 0;
        for (char item : chars) {
            n += toBase10(BASE_62_CHAR.indexOf(item), pow);
            pow++;
        }
        return n;
    }

    private static long toBase10(int n, int pow) {
        return n * (long) Math.pow(BASE, pow);
    }


    public static String fromBase10(long i) {
        StringBuilder sb = new StringBuilder("");
        if (i == 0) {
            return "a";
        }
        while (i > 0) {
            i = fromBase10(i, sb);
        }
        return sb.reverse().toString();
    }

    private static long fromBase10(long i, final StringBuilder sb) {
        int rem = (int) (i % BASE);
        sb.append(BASE_62_CHAR.charAt(rem));
        return i / BASE;
    }

    /***
     * 维护一个全局自增的id(分布式发号器(Distributed ID Generator))，每来一个长url，将其与一个自增id绑定，然后利用base62将该自增id转换为base62字符串，即完成转换。
     * https://cn.soulmachine.me/2017-04-10-how-to-design-tinyurl/
     */
    private long autoIncrId = 10000;

    Map<Long, String> longUrlIdMap = new HashMap<>();

    public long incr() {
        return autoIncrId++;
    }

    public String shorten(String longUrl) {
        long id = incr();
        longUrlIdMap.put(id, longUrl);
        return Base62.fromBase10(id);
    }

    public String lookup(String shortUrl) {
        long id = Base62.toBase10(shortUrl);
        return longUrlIdMap.get(id);
    }

}
